package com.dhcc.DRGsHosp.infra.util;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

/**
 * 配置文件工具,可以保存配置注释，并且保持原配置文件顺序
 * 
 * 
 */
public class Properties {
	private static String POUND = "#";
	private static String EQUAL = "=";
	/**
	 * 行集合（key－value行则只包含key部分）
	 */
	private List<String> keyList = new ArrayList<String>();

	/** 键值对集合（配置文件有效键值对） */
	private Map<String,String> valueMap = new HashMap<String,String>();

	public Map<String,String> getPropertyMap() {
		return valueMap;
	}

	/**
	 * 得到配置文件
	 * 
	 * @param key
	 *            配置键
	 * @return 配置值
	 */
	public String getProperty(String key) {
		return valueMap.get(key);
	}

	/**
	 * 设置配置项
	 * 
	 * @param key
	 *            配置键
	 * @return 配置值
	 */
	public void setProperty(String key, String value) {
		// 处理新增配置项，防止在保存时丢失
		if (!valueMap.containsKey(key)) {
			keyList.add(key);
		}
		valueMap.put(key, value);
	}
	
	public List<String> getKeyList() {
		return keyList;
	}

	/**
	 * 删除配置项
	 * 
	 * @param key
	 *            配置键
	 * @return 配置值
	 */
	public void delProperty(String key, String value) {
		// 处理新增配置项，防止在保存时丢失
		if (valueMap.containsKey(key)) {
			Iterator<String> ikl = keyList.iterator();
			while (ikl.hasNext()) {
				if (ikl.next().equals(key)) {
					ikl.remove();
				}
			}
			valueMap.remove(key);
		}
	}

	/**
	 * 加载.properties文件
	 * 
	 * @param stream
	 *            输入流
	 * @throws Exception
	 *             IO错误
	 */
	public synchronized void load(InputStream stream) throws IOException {
		Reader isr = new InputStreamReader(stream);
		BufferedReader reader = new BufferedReader(isr);
		try {
			while (reader.ready()) {
				saveLine(reader.readLine());
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (reader != null) {
					reader.close();
				}
				if (isr != null) {
					isr.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}

		}
	}

	/**
	 * 保存Properties
	 * 
	 * @param writer
	 *            文件输出对象
	 * @throws IOException 
	 */
	public void store(Writer writer,String comments) throws IOException {
		BufferedWriter bw = new BufferedWriter(writer);
		
		if (comments != null) {
            writeComments(bw, comments);
        }
		
		try {
			for (String key : keyList) {
				bw.write(key);
				if (valueMap.containsKey(key)) {
					bw.write(EQUAL);
					bw.write(valueMap.get(key));
				}
				bw.newLine();
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				if (bw != null) {
					bw.close();
				}
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	
	private static void writeComments(BufferedWriter bw, String comments)
	        throws IOException {
	        bw.write("#");
	        int len = comments.length();
	        int current = 0;
	        int last = 0;
	        char[] uu = new char[6];
	        uu[0] = '\\';
	        uu[1] = 'u';
	        while (current < len) {
	            char c = comments.charAt(current);
	            if (c > '\u00ff' || c == '\n' || c == '\r') {
	                if (last != current)
	                    bw.write(comments.substring(last, current));
	                if (c > '\u00ff') {
	                    uu[2] = toHex((c >> 12) & 0xf);
	                    uu[3] = toHex((c >>  8) & 0xf);
	                    uu[4] = toHex((c >>  4) & 0xf);
	                    uu[5] = toHex( c        & 0xf);
	                    bw.write(new String(uu));
	                } else {
	                    bw.newLine();
	                    if (c == '\r' &&
	                        current != len - 1 &&
	                        comments.charAt(current + 1) == '\n') {
	                        current++;
	                    }
	                    if (current == len - 1 ||
	                        (comments.charAt(current + 1) != '#' &&
	                        comments.charAt(current + 1) != '!'))
	                        bw.write("#");
	                }
	                last = current + 1;
	            }
	            current++;
	        }
	        if (last != current)
	            bw.write(comments.substring(last, current));
	        bw.newLine();
	    }
	
	private static char toHex(int nibble) {
        return hexDigit[(nibble & 0xF)];
    }

    /** A table of hex digits */
    private static final char[] hexDigit = {
        '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'
    };

	/**
	 * 读取流转为行
	 * 
	 * @param istream
	 *            输入流
	 */
	private void saveLine(String line) {
		if (line.trim().startsWith(POUND)) {
			keyList.add(line);
		} else {
			if (line.indexOf(EQUAL) > -1) {
				String k = line.substring(0, line.indexOf(EQUAL)).trim();
				String v = line.substring(line.indexOf(EQUAL) + 1).trim();
				keyList.add(k);
				valueMap.put(k, v);
			} else {
				keyList.add(line);
			}
		}

	}

	@Override
	public String toString() {
		return valueMap.toString();
	}
}